/***************************************************************
|	File:		GameplayState.cpp
|	Author:		Richard Jones
|	Course:		SGD 1404
|	Purpose:	GameplayState class initializes & runs the
|				game logic
***************************************************************/

#include "GameplayState.h"

#include "Game.h"

#include "../SGD Wrappers/SGD_AudioManager.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "../SGD Wrappers/SGD_String.h"

#include "../SGD Wrappers/SGD_EventManager.h"
#include "../SGD Wrappers/SGD_Event.h"
#include "../SGD Wrappers/SGD_MessageManager.h"
#include "../SGD Wrappers/SGD_Message.h"
#include "MessageID.h"

#include "Entity.h"
#include "EntityManager.h"
#include "BitmapFont.h"
#include "DestroyEntityMessage.h"

#include <cstdlib>
#include <cassert>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>


/**************************************************************/
// GetInstance
//	- allocate static global instance
//	- return THE instance
/*static*/ GameplayState* GameplayState::GetInstance( void )
{
	static GameplayState s_Instance;	// stored in global memory once
	return &s_Instance;
}


/**************************************************************/
// Enter
//	- reset game
//	- load resources
//	- set up entities
/*virtual*/ void GameplayState::Enter( void )
{
	// Set background color
	SGD::GraphicsManager::GetInstance()->SetClearColor( {0, 0, 0} );	// black

	// Initialize the Event & Message Managers
	SGD::EventManager::GetInstance()->Initialize();
	SGD::MessageManager::GetInstance()->Initialize( &MessageProc );

	// Allocate the Entity Manager
	m_pEntities = new EntityManager;
}


/**************************************************************/
// Exit
//	- deallocate entities
//	- unload resources
/*virtual*/ void GameplayState::Exit( void )
{
	// Release the game entities


	// Deallocate the Entity Manager
	m_pEntities->RemoveAll();
	delete m_pEntities;
	m_pEntities = nullptr;
	

	// Terminate & deallocate the SGD wrappers
	SGD::EventManager::GetInstance()->Terminate();
	SGD::EventManager::DeleteInstance();

	SGD::MessageManager::GetInstance()->Terminate();
	SGD::MessageManager::DeleteInstance();
}


/**************************************************************/
// Input
//	- handle user input
/*virtual*/ bool GameplayState::Input( void )
{
	return true;	// keep playing
}


/**************************************************************/
// Update
//	- update game entities
/*virtual*/ void GameplayState::Update( float elapsedTime )
{

}


/**************************************************************/
// Render
//	- render the game entities
/*virtual*/ void GameplayState::Render( void )
{	
		// Render the entities
		m_pEntities->RenderAll();
}


/**************************************************************/
// MessageProc
//	- process messages queued in the MessageManager
//	- STATIC METHOD
//		- does NOT have invoking object!!!
//		- must use singleton to access members
/*static*/ void GameplayState::MessageProc( const SGD::Message* pMsg )
{
	// What type of message?
	switch( pMsg->GetMessageID() )
	{
		default:
		case MessageID::MSG_UNKNOWN:
		{
			OutputDebugStringW( L"Game::MessageProc - unknown message id\n" );
		}
		break;
	
		case MessageID::MSG_DESTROY_ENTITY:
		{									  
			// Downcast to the actual message type
			const DestroyEntityMessage* pDestroyMsg = dynamic_cast<const DestroyEntityMessage*>(pMsg);

			assert(pDestroyMsg != nullptr 
				&& "Game::MessageProc - MSG_DESTROY_ENTITY is not actually a DestroyEntityMessage");

			Entity* ptr = pDestroyMsg->GetEntity();

			GameplayState::GetInstance()->m_pEntities->RemoveEntity(ptr);
		}
		break;
	}
}